package service

import (
	"fmt"
	"net"
	"noip_updator/common"
	"strings"

	"github.com/spf13/viper"
)

type IPService struct {
}

func NewIPService() *IPService {
	common.Logger.Info("ip service init...")
	return &IPService{}
}

func (server *IPService) selectInt(name, use string) (targetInterface *net.Interface, err error) {
	candidates, err := net.Interfaces()
	if err != nil {
		return nil, fmt.Errorf("net.Interfaces err:%v", err)
	}
	switch strings.ToLower(use) {
	case "name":
		for _, c := range candidates {
			if c.Name == name {
				targetInterface = &c
				break
			}
		}
	case "mac":
		for _, c := range candidates {
			mac := c.HardwareAddr.String()
			hwAdds, err := net.ParseMAC(name)
			if err != nil {
				return nil, err
			}
			if hwAdds.String() == mac {
				targetInterface = &c
				break
			}
		}
	default:
		err = fmt.Errorf("not acceptable use para:%s", use)
		return
	}
	return
}

// GetUniCastIP 获取公网地址，含v4和v6
func (server *IPService) GetUniCastIP(netInterface *net.Interface) (ips []net.IP, err error) {
	addrs, err := netInterface.Addrs()
	if err != nil {
		return nil, fmt.Errorf("netInterface.Addrs err:%v", err)
	}
	for _, add := range addrs {
		ipnet, ok := add.(*net.IPNet)
		ip := ipnet.IP
		if !ok {
			continue
		}
		// 过滤非单播地址
		if !ip.IsGlobalUnicast() {
			continue
		}
		// 过滤私网地址
		if ip.IsPrivate() {
			continue
		}
		ips = append(ips, ip)
	}
	common.Logger.Infof("update service found %d ips", len(ips))
	return
}

// GetDynIP 获取动态公网ip
func (server *IPService) GetDynIP() (ips []net.IP, err error) {
	return server.getDynIP(viper.GetString("monitor.name"), viper.GetString("monitor.use"))
}

func (server *IPService) getDynIP(name, use string) (ips []net.IP, err error) {
	common.Logger.Infof("update service filter interface by [%s:%s]", use, name)
	targetInterface, err := server.selectInt(name, use)
	if err != nil {
		err = fmt.Errorf("ipp.selectInt err:%s", err.Error())
		return
	}
	return server.GetUniCastIP(targetInterface)
}

// GetDynIPByName 通过端口Name获取动态IP信息
func (server *IPService) GetDynIPByName(intName string) (ips []net.IP, err error) {
	targetInterface, err := server.selectInt(intName, "name")
	if err != nil {
		err = fmt.Errorf("ipp.selectInt err:%s", err.Error())
		return
	}
	return server.GetUniCastIP(targetInterface)
}

// GetDynIPByIntMac 通过端口MAC获取动态IP信息
func (server *IPService) GetDynIPByIntMac(intMac string) (ips []net.IP, err error) {
	targetInterface, err := server.selectInt(intMac, "mac")
	if err != nil {
		err = fmt.Errorf("ipp.selectInt err:%s", err.Error())
		return
	}
	return server.GetUniCastIP(targetInterface)
}
